﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using RedSand.Site.Models;
using RedSand.Web.Mvc;
using System.Web.Security;
using System.Net.Mail;

namespace RedSand.Site.Controllers
{
    public class AccountController : BaseController
    {
        public ActionResult Index()
        {
            return View();
        }
        public ActionResult Manager()
        {
            return View(new ManagerModel { Title = "Account manager" });
        }
        [AjaxOrChildAction]
        public ActionResult List(SearchUsersModel searchModel, int? page)
        {
            int Total = 0;
            List<UserInfo> list = RsDataManager.GetList<UserInfo>("UserSearch", searchModel, page ?? 1, 10, ref Total);
            if (list != null) list = list.Where(item => item.Username != "admin").ToList();
            ViewBag.TotalRecord = Total - 1;
            ViewBag.RouteValues = searchModel;
            return PartialView(list);
        }
        [HttpGet, AjaxOrChildAction]
        public ActionResult Create()
        {
            return PartialView();
        }
        [HttpPost, AjaxOrChildAction]
        public ActionResult Create(UserInfo info, string ConfirmPassword, string[] Check)
        {
            if (ModelState.IsValid)
            {
                Check = Check ?? new string[0];
                if (info.Password != ConfirmPassword)
                {
                    return AjaxMessage("Password not match");
                }
                if (RsDataManager.ExecuteGetReturn("UserCheckUser", new { UserID = 0, UserName = info.Username, Email = info.Email }) > 0)
                {
                    return AjaxMessage("Username or email is in use");
                }
                info.JoinDate = DateTime.Now;
                info.Password = RedSand.Web.Security.RsEncryption.GetMd5Hash(info.Password);
                info.IsAdmin = Check.Contains("1");
                if (RsDataManager.Save("UserSave", info, new { RoleIDs = "[" + string.Join("][", Check) + "]" }) > 0)
                {
                    AddMessage(Message.CreateSuccess);
                    return RedirectToAction("List");
                }
                return AjaxMessage(Message.CreateError);
            }
            return AjaxModelError();
        }
        [HttpGet, AjaxOrChildAction]
        public ActionResult Edit(int id)
        {
            return PartialView(RsDataManager.GetInfo<UserInfo>("UserGetInfo", "UserID", id));
        }
        [HttpPost, AjaxOrChildAction]
        public ActionResult Edit(UserInfo info, string[] Check)
        {
            if (ModelState.IsValid)
            {
                Check = Check ?? new string[0];
                if (RsDataManager.ExecuteGetReturn("UserCheckUser", new { UserID = info.UserID, UserName = info.Username, Email = info.Email }) > 1)
                {
                    return AjaxMessage("Email is in use");
                }
                info.JoinDate = info.JoinDate ?? DateTime.Now;
                info.IsAdmin = Check.Contains("1");
                if (RsDataManager.Save("UserSave", info, new { RoleIDs = "[" + string.Join("][", Check) + "]" }) > 0)
                {
                    AddMessage(Message.UpdateSuccess);
                    return RedirectToAction("List");
                }
                return AjaxMessage(Message.UpdateError);
            }
            return AjaxModelError();
        }
        [AjaxOrChildAction]
        public ActionResult Delete(int id)
        {
            UserInfo info = RsDataManager.GetInfo<UserInfo>("UserGetInfo", "UserID", id);
            if (RsDataManager.Delete("UserDelete", "UserID", id))
            {
                if (info.Username == User.Identity.Name)
                {
                    FormsAuthentication.SignOut();
                    AddMessage("Your account has been delete");
                    return RedirectToLogin();
                }
                AddMessage(Message.DeleteSuccess);
                return RedirectToAction("List");
            }
            return AjaxMessage(Message.DeleteError);
        }

        [HttpGet]
        public ActionResult Login()
        {
            return View();
        }

        [HttpPost]
        public ActionResult Login(LoginModel model, string returnUrl)
        {
            if (ModelState.IsValid)
            {
                UserID = RsDataManager.ExecuteGetReturn("UserValidate", new { UserName = model.Username, Password = RedSand.Web.Security.RsEncryption.GetMd5Hash(model.Password) });
                if (UserID > 0)
                {
                    FormsAuthentication.SetAuthCookie(model.Username, model.RememberMe);
                    if (Url.IsLocalUrl(returnUrl) && returnUrl.Length > 1)
                    {
                        return Redirect(returnUrl);
                    }
                    else
                    {
                        return Redirect("/admin");
                    }
                }
                else
                {
                    AddMessage("Username or password wrong");
                }
            }
            else
            {
                AddMessage("Username or password wrong");
            }
            return View();
        }

        public ActionResult Logout()
        {
            Session.RemoveAll();
            FormsAuthentication.SignOut();
            return Redirect("/");
        }
        [HttpGet, AjaxOrChildAction]
        public ActionResult ChangePassword(int? id)
        {
            ViewBag.UserID = id ?? UserID;
            return PartialView();
        }
        [HttpPost, AjaxOrChildAction]
        public ActionResult ChangePassword(ChangePasswordModel model, int UserID)
        {
            if (ModelState.IsValid)
            {
                if (model.NewPassword != model.ConfirmPassword)
                {
                    return AjaxMessage("Password not match");
                }
                string oldPass = RedSand.Web.Security.RsEncryption.GetMd5Hash(model.OldPassword);
                string newPass = RedSand.Web.Security.RsEncryption.GetMd5Hash(model.NewPassword);
                if (RsDataManager.ExecuteGetReturn("UserChangePassword", new { OldPassword = oldPass, NewPassword = newPass, UserID = UserID }) <= 0)
                {
                    return AjaxMessage("Old password wrong");
                }
                return Json("");
            }
            return PartialView();
        }

        [Authorize]
        public ActionResult Profile()
        {
            return View(RsDataManager.GetInfo<UserInfo>("UserGetInfo", new { UserName = User.Identity.Name }));
        }

        [HttpGet, AjaxOrChildAction]
        public ActionResult ChangeProfile()
        {
            return PartialView(RsDataManager.GetInfo<UserInfo>("UserGetInfo", new { UserName = User.Identity.Name }));
        }
        [HttpPost, AjaxOrChildAction]
        public ActionResult ChangeProfile(UserInfo info)
        {
            if (ModelState.IsValid)
            {
                if (RsDataManager.ExecuteGetReturn("UserCheckUser", new { UserID = info.UserID, UserName = info.Username, Email = info.Email }) > 1)
                {
                    return AjaxMessage("Email is in use");
                }
                info.Username = User.Identity.Name;
                info.UserID = UserID;
                List<RoleCheckListModel> listRole = RsDataManager.GetList<RoleCheckListModel>("RoleGetRoleForUser", new { UserID = info.UserID });
                if (listRole != null) listRole = listRole.Where(item => item.Check).ToList();
                string[] roleIDs = new string[listRole.Count];
                for (int i = 0; i < listRole.Count; i++)
                {
                    roleIDs[i] = listRole[i].RoleID.ToString();
                }
                if (RsDataManager.Save("UserSave", info) > 0)
                {
                    return RedirectToAction("Profile");
                }
                return AjaxMessage(Message.UpdateError);
            }
            return AjaxModelError();
        }

        public MvcHtmlString GetAvatar()
        {
            var info = RsDataManager.GetInfo<UserInfo>("UserGetInfo", "UserID", UserID);
            string avatar = info.Avatar ?? "/content/frontend/images/no-avt.jpg";
            return MvcHtmlString.Create("<img alt='" + User.Identity.Name + "' src='" + avatar + "' class='avatar'/>");
        }

        public ActionResult feGetTopPoster()
        {
            return PartialView(RsDataManager.GetList<Poster>("UserGetTopPoster"));
        }

        [HttpGet]
        public ActionResult feRegister()
        {
            return View();
        }
        [HttpPost]
        public ActionResult feRegister(UserInfoFe info)
        {
            if (ModelState.IsValid)
            {
                if (RsDataManager.ExecuteGetReturn("UserCheckUser", new { UserID = 0, UserName = info.Username, Email = info.Email }) > 0)
                {
                    AddMessage("UserName Or Email Is In Use");
                }
                if (!RedSand.Web.Mvc.Controls.RsCaptcha.IsVaild(info.captcha_code, info.captcha, false))
                {
                    AddMessage("Security Code is not match");
                }
                if (!MvcHtmlString.IsNullOrEmpty(GetMessage(false))) return View(info);

                info.Password = RedSand.Web.Security.RsEncryption.GetMd5Hash(info.Password);
                if (!string.IsNullOrWhiteSpace(info.Avatar)) info.Avatar = SaveImage(null);

                var infocreate = new UserInfo { Username = info.Username, Fullname = info.Fullname, Email = info.Email, Password = info.Password, Status = 1, Avatar = info.Avatar, JoinDate = DateTime.Now, IsAdmin = false };

                if (RsDataManager.Save("UserSave", infocreate, new { RoleIDs = "[3]" }) > 0)
                {
                    FormsAuthentication.SetAuthCookie(info.Username, false);
                    return Redirect("/");
                }
            }
            AddMessage("Some invalid data"); 
            return View(info);
        }
        [HttpGet, Authorize]
        public ActionResult feEditProfile()
        {
            var info = RsDataManager.GetInfo<UserChangeProfile>("UserGetInfo", new { UserName = User.Identity.Name });
            return View(info);
        }

        [HttpPost, Authorize]
        public ActionResult feEditProfile(UserChangeProfile info, string NewAvatar)
        {
            if (RsDataManager.ExecuteGetReturn("UserCheckUser", new { UserID = info.UserID, UserName = info.Username, Email = info.Email }) == 2)
            {
                AddMessage("Email Is In Use");
                return View(info);
            }
            info.UserID = UserID;
            info.Username = User.Identity.Name;
            if (!string.IsNullOrWhiteSpace(NewAvatar))
            {
                info.Avatar = SaveImage(info.Avatar);
            }

            if (RsDataManager.ExecuteGetReturn("UserfeChangeProfile", info) > 0)
            {
                AddMessage("Change profile success");
            }
            else
            {
                AddMessage("Change profile error");
            }

            return View(info);

        }
        [HttpGet, Authorize]
        public ActionResult feChangePassword()
        {
            return View();
        }
        [HttpPost, Authorize]
        public ActionResult feChangePassword(ChangePasswordModel info)
        {
            if (ModelState.IsValid)
            {
                if (info.NewPassword != info.ConfirmPassword)
                {
                    AddMessage("Password not match");
                }
                string oldPass = RedSand.Web.Security.RsEncryption.GetMd5Hash(info.OldPassword);
                string newPass = RedSand.Web.Security.RsEncryption.GetMd5Hash(info.NewPassword);
                if (RsDataManager.ExecuteGetReturn("UserChangePassword", new { OldPassword = oldPass, NewPassword = newPass, UserID = UserID }) > 0)
                {
                    AddMessage("Change password success");
                    return RedirectToAction("feEditProfile");
                }
                AddMessage("Old password wrong");
            }
            return View();
        }
        [HttpGet]
        public ActionResult feForgotPassword()
        {
            return View();
        }
        [HttpPost]
        public ActionResult feForgotPassword(LostPasswordModel info)
        {
            if (ModelState.IsValid)
            {
                if (RsDataManager.ExecuteGetReturn("UserCheckUser", new { UserID = 0, UserName = info.Username, Email = info.Email }) == 3)
                {
                    MailMessage message = new MailMessage();
                    var uinfo = RsDataManager.GetInfo<UserInfo>("UserGetInfo", new { UserName = info.Username });
                    string body = "";
                    string username = RedSand.Web.Security.RsEncryption.TripleDESEncrypt("@recover@username", uinfo.Username);
                    string datetime = RedSand.Web.Security.RsEncryption.TripleDESEncrypt("@recover@datetime", DateTime.Now.Ticks.ToString());
                    string link = Request.Url.Scheme + "://" + Request.Url.Authority + "/recover/" + username + "/" + uinfo.Password + "/" + Url.Encode(datetime) + "";
                    body += "<b>Hello " + uinfo.Username + "</b><br/>";
                    body += "<p>You recently asked to reset your password. To complete your request, please follow this link:</p>";
                    body += "<p><a href='" + link + "'>" + link + "</a></p>";
                    body += "<p>If not, please disregard this email.<br/>Link restoration is valid only within 24 hours.<br/>Thank you very much.</p>";

                    message.Subject = "Request a password reset";
                    message.Body = body;
                    message.IsBodyHtml = true;
                    message.To.Add(info.Email);

                    try
                    {
                        SmtpClient client = new SmtpClient();
                        client.Send(message);
                        AddMessage("We are processing request, please check your email to get recovery password link.");
                    }
                    catch
                    {
                        AddMessage("A problem occurred sending the email. Please contact the system administrator.");
                    }
                }
                else
                {
                    AddMessage("Username or email wrong");
                }
            }
            return View();
        }
        [HttpGet]
        public ActionResult feResetPassword(string username, string password, string datetime)
        {
            datetime = RedSand.Web.Security.RsEncryption.TripleDESDecrypt("@recover@datetime", datetime);
            username = RedSand.Web.Security.RsEncryption.TripleDESDecrypt("@recover@username", username);
            DateTime date = new DateTime(long.Parse(datetime));
            int userid = RsDataManager.ExecuteGetReturn("UserValidate", new { UserName = username, Password = password });
            if ((DateTime.Now - date).Hours > 24 || userid <= 0)
            {
                return View();
            }
            return View(new ResetPasswordModel { UserID = userid, OldPassword = password });
        }
        [HttpPost]
        public ActionResult feResetPassword(ResetPasswordModel info)
        {
            if (ModelState.IsValid)
            {
                if (info.NewPassword != info.ConfirmPassword)
                {
                    AddMessage("Password not match");
                }
                string newPass = RedSand.Web.Security.RsEncryption.GetMd5Hash(info.NewPassword);
                if (RsDataManager.ExecuteGetReturn("UserChangePassword", new { OldPassword = info.OldPassword, NewPassword = newPass, UserID = info.UserID }) > 0)
                {
                    AddMessage("Reset password success");
                    return Redirect("/");
                }
                AddMessage("System error, please contact system administrator");
            }
            return View(info);
        }
    }
}
